/* ForwardEuler.h
 *
 *	Copyright (C) 2008 CRIMERE
 *	Copyright (C) 2008 Jean-Marc Mercier
 *	
 *	This file is part of OTS (optimally transported schemes), an open-source library
 *	dedicated to scientific computing. http://code.google.com/p/optimally-transported-schemes/
 *
 *	CRIMERE makes no representations about the suitability of this
 *	software for any purpose. It is provided "as is" without express or
 *	implied warranty.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 */

#if !defined(_Euler_)
#define _Euler_

#include <src/algorithm/Evolution_Algorithm/TimeStepAlgorithm.h>


template <	class TimeTypeOperator >
class Euler : 
	public TimeStepAlgorithm<TimeTypeOperator>
{
public:
	typedef typename Euler											type;
	typedef TimeStepAlgorithm<TimeTypeOperator>						Base;
	typedef typename TimeTypeOperator::argument_base_type			data;
	typedef typename TimeTypeOperator::result_type					result_type;
	typedef result_type												solution_type;
	typedef typename TimeTypeOperator::argument_type				argument_type;
	typedef typename TimeTypeOperator::indice_type					indice_type;

	Euler() : n_(0) {};
	Euler(const time_operator_type & Op	) : Base(Op)
	{};
	virtual ~Euler(){};


	virtual OS_double CFL() = 0;
	virtual OS_double next_time(time_type to) {
		to_ = from_ + std::min(to-from_, delta_t_);
		delta_t_ = to_ - from_;
		return to_;
	};
	virtual void operator ++() {
		u_ += delta_t_ * Op_(from_,u_);
	};


	result_type operator()(const time_type & from, time_type & to, argument_type S_k) 
	{
		from_ = from;
		to_   = to;
		delta_t_ = CFL();
		to = next_time(to);
		++(*this);
		return u_;
	};
	virtual void update(){
		if (u_.size(1) != get_state_variable()->size(1))
			u_ = *get_state_variable();
		Op_.set_state_variable(get_state_variable());
	}; 
	static std::string get_name(){return " Euler delta_t u = ";};
	data    u_;
	indice_type n_;
	OS_double delta_t_, from_, to_;
};

#endif
